<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <p data-lake-id="ub83b8eb1" id="ub83b8eb1"><span data-lake-id="u4fd6ed60" id="u4fd6ed60">Redis的性能很好，除了因为他基于内存、有高效的数据结构等等原因以外，还有一个重要的原因那就是他在单线程中使用多路复用 I/O技术也能提升Redis的I/O利用率。</span></p>
  <p data-lake-id="uf9b09454" id="uf9b09454"><span data-lake-id="u7e92a8d1" id="u7e92a8d1">​</span><br></p>
  <p data-lake-id="ua821e0e0" id="ua821e0e0"><br></p>
  <h3 data-lake-id="qlO0I" id="qlO0I"><span data-lake-id="u819ccefe" id="u819ccefe">Redis的多路复用</span></h3>
  <p data-lake-id="u87bca6ad" id="u87bca6ad"><br></p>
  <p data-lake-id="udaf8957f" id="udaf8957f"><span data-lake-id="u94c7d4f0" id="u94c7d4f0">多路复用这个词，相信很多人都不陌生。那么，Redis的多路复用技术有什么特别的呢？</span></p>
  <p data-lake-id="u5faa0271" id="u5faa0271"><br></p>
  <p data-lake-id="u9c5fa13c" id="u9c5fa13c"><span data-lake-id="uf5c581e0" id="uf5c581e0">这里先讲讲</span><strong><span data-lake-id="uf4998aeb" id="uf4998aeb">Linux多路复用技术，就是多个进程的IO可以注册到同一个管道上，这个管道会统一和内核进行交互。当管道中的某一个请求需要的数据准备好之后，进程再把对应的数据拷贝到用户空间中。</span></strong></p>
  <p data-lake-id="u1e2c7c18" id="u1e2c7c18"><br></p>
  <p data-lake-id="u4a0aa070" id="u4a0aa070"><img src="https://cdn.nlark.com/yuque/0/2022/jpeg/5378072/1671869113602-d513bd05-7ec3-4ad9-adbb-e32e3d9f3856.jpeg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="u4b765820" id="u4b765820">​</span></p>
  <p data-lake-id="u04864da3" id="u04864da3"><br></p>
  <p data-lake-id="u96b28499" id="u96b28499"><span data-lake-id="ud7109e76" id="ud7109e76">多看一遍上面这张图和上面那句话，后面可能还会用得到。</span></p>
  <p data-lake-id="ub00f7171" id="ub00f7171"><br></p>
  <p data-lake-id="ubc0c51d3" id="ubc0c51d3"><span data-lake-id="u09571e6f" id="u09571e6f">也就是说，通过一个线程来处理多个IO流。</span></p>
  <p data-lake-id="uead4ece3" id="uead4ece3"><br></p>
  <p data-lake-id="u66329529" id="u66329529"><span data-lake-id="u7ca5750e" id="u7ca5750e">IO多路复用在Linux下包括了三种，select、poll、epoll，抽象来看，他们功能是类似的，但具体细节各有不同。</span></p>
  <p data-lake-id="u2406f6bf" id="u2406f6bf"><br></p>
  <p data-lake-id="ud31efb66" id="ud31efb66"><span data-lake-id="u6bc0fcea" id="u6bc0fcea">其实，Redis的IO多路复用程序的所有功能都是通过包装操作系统的IO多路复用函数库来实现的。每个IO多路复用函数库在Redis源码中都有对应的一个单独的文件。</span></p>
  <p data-lake-id="u599d3613" id="u599d3613"><br></p>
  <p data-lake-id="u4c4efa1c" id="u4c4efa1c"><img src="https://cdn.nlark.com/yuque/0/2022/jpeg/5378072/1671869113599-53d7dd5b-2958-4d86-99a1-1b18b8194534.jpeg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="ua170c328" id="ua170c328">￼</span></p>
  <p data-lake-id="u9e6244d0" id="u9e6244d0"><br></p>
  <p data-lake-id="u8f53b0ef" id="u8f53b0ef"><span data-lake-id="ua4527892" id="ua4527892">在Redis 中，每当一个套接字准备好执行连接应答、写入、读取、关闭等操作时，就会产生一个文件事件。因为一个服务器通常会连接多个套接字，所以多个文件事件有可能会并发地出现。</span></p>
  <p data-lake-id="ua043b9df" id="ua043b9df"><br></p>
  <p data-lake-id="u2d94a3ec" id="u2d94a3ec"><img src="https://cdn.nlark.com/yuque/0/2022/jpeg/5378072/1671869113602-bf07074d-d7e4-48c1-808f-e265e9d17daf.jpeg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_17%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"><span data-lake-id="u61242753" id="u61242753">￼</span></p>
  <p data-lake-id="u144e4dd0" id="u144e4dd0"><br></p>
  <p data-lake-id="uac9fb11a" id="uac9fb11a"><span data-lake-id="u7d713899" id="u7d713899">一旦有请求到达，就会交给 Redis 线程处理，这就实现了一个 Redis 线程处理多个 IO 流的效果。</span></p>
  <p data-lake-id="u62d1e9f7" id="u62d1e9f7"><br></p>
  <p data-lake-id="u44916062" id="u44916062"><span data-lake-id="ue40eee3e" id="ue40eee3e">所以，Redis选择使用多路复用IO技术来提升I/O利用率。</span></p>
  <p data-lake-id="ua1211ac4" id="ua1211ac4"><br></p>
  <p data-lake-id="ud1de0e63" id="ud1de0e63"><span data-lake-id="u7add54e8" id="u7add54e8">而之所以Redis能够有这么高的性能，不仅仅和采用多路复用技术和单线程有关，此外还有以下几个原因：</span></p>
  <p data-lake-id="u0a617701" id="u0a617701"><br></p>
  <ul list="u397d8a9d">
   <li fid="u0258d844" data-lake-id="u503e3514" id="u503e3514"><span data-lake-id="ufef6524f" id="ufef6524f"> 1、完全基于内存，绝大部分请求是纯粹的内存操作，非常快速。 </span></li>
   <li fid="u0258d844" data-lake-id="u741585da" id="u741585da"><span data-lake-id="udc17853d" id="udc17853d"> 2、数据结构简单，对数据操作也简单，如哈希表、跳表都有很高的性能。 </span></li>
   <li fid="u0258d844" data-lake-id="u83f1394e" id="u83f1394e"><span data-lake-id="u9a028b96" id="u9a028b96"> 3、采用单线程，避免了不必要的上下文切换和竞争条件，也不存在多进程或者多线程导致的切换而消耗 CPU </span></li>
   <li fid="u0258d844" data-lake-id="uf8aca57e" id="uf8aca57e"><span data-lake-id="ud81df3fe" id="ud81df3fe"> 4、使用多路I/O复用模型 </span></li>
  </ul>
  <p data-lake-id="u1b33a405" id="u1b33a405"><br></p>
 </body>
</html>